import os
import sys
import logging
import copy

from command_parser.command_generate import GenCommand
from command_parser.option_context import OptionContext
from command_parser.clang_parse.clang_option_filter import ClangFilter
from utils.common_utils import *

class ClangGenCommand(GenCommand):
    def __init__(self, context=None, cwd=""):
        super().__init__(context, cwd)
        self.option_context = OptionContext()
        self.command_filter = ClangFilter(context=context, option_context=self.option_context)
    
    def generate_divided_compile_command(self, compiler="", options=[]):
        if not compiler or not options:
            raise Exception("It occurs fails when generate_divided_compile_command")
        
        command = [compiler]
        local_options = copy.deepcopy(options)
        
        self.command_filter.filter_link_options(options=local_options)
        self.command_filter.append_option_compile(option=local_options)
        
        for option in local_options:
            command.extend(option.get_option())
        
        return command
    
    def generate_divided_link_command(self, compiler="", options=[]):
        if not compiler or not options:
            raise Exception("It occurs fails when generate_divided_link_command")
        
        command_line = [compiler]
        local_options = copy.deepcopy(options)
        
        self.command_filter.filter_compile_options(options=local_options)
        
        for option in local_options:
            command_line.extend(option.get_option())
            
        return command_line
    
    def generate_clang_ast_command(self, parser=None, compiler="", options=[]):
        
        if not compiler or not options or not parser:
            raise Exception("It occurs fails when generate clang ast command")
        
        maple_compiler = self.context.MAPLE_CLANG
        if is_cpp_compiler(compiler=compiler):
            maple_compiler = self.context.MAPLE_CLANGCPP
            
        local_options = options
        
        self.command_filter.filter_option_default(options=local_options)
        self.command_filter.filter_link_options(options=local_options)
        self.command_filter.filter_compile_options(options=local_options)
        self.command_filter.append_clang_spec_options(options=local_options)
        self.command_filter.append_option_clang_ast(options=local_options)
        self.command_filter.append_option_include_custom_path(option=local_options)
        self.command_filter.append_option_include_path(option=local_options)
        # self.command_filter.append_option_target(options=local_options)
        self.command_filter.append_option_debug(options=local_options)
        self.command_filter.append_option_fpic(options=local_options)
        self.command_filter.append_option_flto(option=local_options)
        self.command_filter.append_option_wno_error(options=local_options)
        self.command_filter.filter_unkeep_options(local_options)
        
        command_line = [maple_compiler]
        for opt in options:
            command_line.extend(opt.get_option())
            
        return command_line
    
    
    def generate_retry_clang_ast_command(self, parser=None, compiler="", options=[]):
        return self.generate_clang_ast_command(parser, compiler, options)
    
    
    def generate_clang_ast_command_with_sys_headers(self, parser=None, compiler="", options=[]):
        return self.generate_clang_ast_command(parser, compiler, options)
    
    
    def generate_maple_ir_command(self, parser=None, compiler="", input_file=""):
        
        if not parser or not compiler or not input_file:
            raise Exception("It occurs fails when generate_maple_ir_command")
        
        compiler = self.context.MAPLE_BIN
        command_line = [compiler]
        command_line.append(input_file)
        
        output_file = os.path.join(self.context.MAPLE_DIR, os.path.splitext(os.path.basename(input_file))[0] + self.context.MAPLE_EXT)
        command_line.extend(["-o", output_file])
        
        return command_line
    
    
    def generate_assemble_maple_ir_command(self, parser=None, compiler="", options=[]):
        
        ast_command = self.generate_clang_ast_command(parser=parser, compiler=compiler, options=options)
        
        output_opt = parser.get_output_options()
        output_file = output_opt[0].parameter[0]
        dst_md5 = os.path.splitext(os.path.basename(output_file))[0]
        ast_path = os.path.join(self.context.AST_DIR, dst_md5 + self.context.AST_EXT)
        
        ir_command = self.generate_maple_ir_command(parser=parser, compiler=self.context.MAPLE_BIN, input_file=ast_path)
        
        return [ast_command, ir_command]
        
        
        

